package guiLayer;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

import modelLayer.Forest;
import modelLayer.Owner;
import modelLayer.Tree;

import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

import controlerLayer.ForestCtr;
import controlerLayer.OwnerCtr;

public class CreaterTree extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTextField txtSort;
	private JTextField txtLifeSpan;
	private JLabel lblSort;
	private JLabel lblLifeSpan;
	private JPanel panel_2;
	private JButton btnClear;
	private JButton btnCreate;
	private JPanel panel;
	private JPanel panel_1;
	private JLabel lblTitle;
	private JLabel lblCreated;
	private JLabel lblSquareKm;
	private JTextField txtSquare;
	private JLabel lblCost;
	private JTextField txtCost;
	private JLabel lblRevenuePerKm;
	private JTextField txtRevenue;
	private JLabel lblOwner;
	private JLabel lblForest;
	private JComboBox<String> cmbOwner;
	private JComboBox<String> cmbForest;
	private JLabel lblError1;
	private JLabel lblError2;
	private JLabel lblError4;
	private JLabel lblError5;
	private JLabel lblError6;
	private JLabel lblError7;
	private JLabel lblError8;
	private Tree t;
	private Updater updater;
	
	/**
	 * Create the panel.
	 */
	public CreaterTree(final Tree t, final Updater updater) {
		this.t = t;
		this.updater = updater;
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{458, 183, 0};
		gridBagLayout.rowHeights = new int[]{0, 0};
		gridBagLayout.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
		gridBagLayout.rowWeights = new double[]{1.0, Double.MIN_VALUE};
		setLayout(gridBagLayout);
		
		panel_1 = new JPanel();
		GridBagConstraints gbc_panel_1 = new GridBagConstraints();
		gbc_panel_1.insets = new Insets(0, 0, 0, 5);
		gbc_panel_1.fill = GridBagConstraints.BOTH;
		gbc_panel_1.gridx = 0;
		gbc_panel_1.gridy = 0;
		add(panel_1, gbc_panel_1);
		panel_1.setLayout(new FormLayout(new ColumnSpec[] {
				ColumnSpec.decode("max(40dlu;min)"),
				FormFactory.RELATED_GAP_COLSPEC,
				ColumnSpec.decode("default:grow"),
				FormFactory.RELATED_GAP_COLSPEC,
				ColumnSpec.decode("100dlu"),},
			new RowSpec[] {
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("20px"),
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("20px"),
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("20px"),
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("20px"),
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,}));
		
		lblTitle = new JLabel("Create Tree");

		lblTitle.setFont(new Font("SansSerif", Font.BOLD, 13));
		panel_1.add(lblTitle, "1, 1, 3, 1, center, default");
		
		lblOwner = new JLabel("Owner");
		panel_1.add(lblOwner, "1, 3, left, default");
		
		cmbOwner = new JComboBox<String>();
		cmbOwner.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent arg0) {
				if(arg0.getStateChange() == ItemEvent.SELECTED){
					selectedOwner((String)arg0.getItem());
				}
			}
		});
		panel_1.add(cmbOwner, "3, 3, fill, default");
		
		lblError1 = new JLabel("");
		panel_1.add(lblError1, "5, 3");
		
		lblForest = new JLabel("Forest");
		panel_1.add(lblForest, "1, 5, left, default");
		
		cmbForest = new JComboBox<String>();
		panel_1.add(cmbForest, "3, 5, fill, default");
		
		lblError2 = new JLabel("");
		panel_1.add(lblError2, "5, 5");
		
		lblSort = new JLabel("Sort");
		panel_1.add(lblSort, "1, 7, left, default");
		
		txtSort = new JTextField();
		panel_1.add(txtSort, "3, 7, fill, default");
		txtSort.setColumns(10);
		
		lblError4 = new JLabel("");
		panel_1.add(lblError4, "5, 7");
		
		lblLifeSpan = new JLabel("Lifespan");
		panel_1.add(lblLifeSpan, "1, 9, left, default");
		
		txtLifeSpan = new JTextField();
		panel_1.add(txtLifeSpan, "3, 9, fill, default");
		txtLifeSpan.setColumns(10);
		
		lblError5 = new JLabel("");
		panel_1.add(lblError5, "5, 9");
		
		lblSquareKm = new JLabel("KM2");
		panel_1.add(lblSquareKm, "1, 11, left, default");
		
		txtSquare = new JTextField();
		txtSquare.setColumns(10);
		panel_1.add(txtSquare, "3, 11, fill, default");
		
		lblError6 = new JLabel("");
		panel_1.add(lblError6, "5, 11");
		
		lblCost = new JLabel("Cost Per KM2");
		panel_1.add(lblCost, "1, 13, left, default");
		
		txtCost = new JTextField();
		txtCost.setColumns(10);
		panel_1.add(txtCost, "3, 13, fill, default");
		
		lblError7 = new JLabel("");
		panel_1.add(lblError7, "5, 13");
		
		lblRevenuePerKm = new JLabel("Revenue Per KM2");
		panel_1.add(lblRevenuePerKm, "1, 15, left, default");
		
		txtRevenue = new JTextField();
		txtRevenue.setColumns(10);
		panel_1.add(txtRevenue, "3, 15, fill, default");
		
		lblError8 = new JLabel("");
		panel_1.add(lblError8, "5, 15");
		
		lblCreated = new JLabel("");
		lblCreated.setHorizontalAlignment(SwingConstants.CENTER);
		panel_1.add(lblCreated, "1, 17, 3, 1");
		
		panel_2 = new JPanel();
		panel_1.add(panel_2, "1, 19, 3, 1, fill, fill");
		panel_2.setLayout(new FormLayout(new ColumnSpec[] {
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.GROWING_BUTTON_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.GROWING_BUTTON_COLSPEC,},
			new RowSpec[] {
				FormFactory.DEFAULT_ROWSPEC,}));
		
		btnClear = new JButton("Clear");
		btnClear.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(t != null){
					updater.closeMe(CreaterTree.this);
				}else{
					clear();
				}
			}
		});
		panel_2.add(btnClear, "2, 1");
		
		btnCreate = new JButton("Create");
		btnCreate.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(t == null){
					createTree();
				}else{
					updateTree();
				}
			}
		});
		panel_2.add(btnCreate, "4, 1");
		
		panel = new JPanel();
		GridBagConstraints gbc_panel = new GridBagConstraints();
		gbc_panel.fill = GridBagConstraints.BOTH;
		gbc_panel.gridx = 1;
		gbc_panel.gridy = 0;
		add(panel, gbc_panel);
		
		addAncestorListener(new AncestorListener() {
			public void ancestorAdded(AncestorEvent arg0) {
				redrawOwner();
			}
			public void ancestorMoved(AncestorEvent arg0) {
			}
			public void ancestorRemoved(AncestorEvent arg0) {
			}
		});
		
		if(t != null){
			btnClear.setText("Cancel");
			lblTitle = new JLabel("Update Tree");
			btnCreate.setText("Update");
			txtSort.setText(t.getSort());
			txtSquare.setText("" + t.getSquareKilometer());
			txtLifeSpan.setText(t.getLifespan() + "");
			txtRevenue.setText(t.getRevenuePerSquareKilometer() + "");
			txtCost.setText(t.getCostPerSquareKilometer() + "");
			
			Forest f = t.getForest();
			
			if(f.getOwner() == null){
				cmbOwner.setSelectedItem("None");
				selectedOwner(null);
			}else{
				selectedOwner(f.getOwner().getName());
				cmbOwner.setSelectedItem(f.getOwner().getName());
			}
			
			cmbForest.setSelectedItem(f.getName());
			
			cmbOwner.setEnabled(false);
		}
	}

	protected void selectedOwner(String name) {
		OwnerCtr oCtr = new OwnerCtr();
		if(name == null || name.equals("None")){
			redrawForest(null);
		}else{
			redrawForest(oCtr.getOwner(name));
		}
	}

	private void error(final JLabel lbl, final String errorMsg){
		Thread errorThread = new Thread(){
			public void run(){
				lbl.setForeground(Color.RED);
				lbl.setText(errorMsg);
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				lbl.setText("");
			}
		};
		
		errorThread.start();
	}
	
	private void created(final JLabel lbl, final String msg){
		Thread createdThread = new Thread(){
			public void run(){
				lbl.setForeground(Color.GREEN);
				lbl.setText(msg);
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				lbl.setText("");
			}
		};
		
		createdThread.start();
	}
	
	private void clear() {
		txtSort.setText("");
		txtLifeSpan.setText("");
		txtCost.setText("");
		txtRevenue.setText("");
		txtSquare.setText("");
		if(cmbOwner.getItemCount() > 0){
			cmbOwner.setSelectedIndex(0);
			OwnerCtr oCtr = new OwnerCtr();
			if(!cmbOwner.getSelectedItem().equals("None")){
				redrawForest(oCtr.findOwner((String)cmbOwner.getSelectedItem()));
			}else{
				redrawForest(null);
			}
			try{
				cmbForest.setSelectedIndex(0);
			}catch(IllegalArgumentException e){
				
			}
			
		}
		
	}
	
	private void redrawOwner(){
		String selected = null;
		
		if(cmbOwner.getItemCount() > 0){
			selected = (String)cmbOwner.getSelectedItem();
		}
		
		DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
		OwnerCtr oCtr = new OwnerCtr();
		ArrayList<Owner> owners = oCtr.getAllOwners();
		model.addElement("None");
		for(Owner o : owners){
			model.addElement(o.getName());
		}
		
		cmbOwner.setModel(model);
		
		if(selected != null){
			cmbOwner.setSelectedItem(selected);
			selectedOwner((String)cmbOwner.getSelectedItem());
		}else if(t != null){
			Forest f = t.getForest();
			
			if(f.getOwner() == null){
				cmbOwner.setSelectedItem("None");
			}else{
				selectedOwner(f.getOwner().getName());
				cmbOwner.setSelectedItem(f.getOwner().getName());
			}
		}else{
			selectedOwner(null);
		}		
		
	}
	
	private void redrawForest(Owner o){
		String selected = null;
		
		if(cmbForest.getItemCount() > 0){
			selected = (String)cmbForest.getSelectedItem();
		}
		
		ArrayList<Forest> forests = new ArrayList<Forest>();
		
		if(o == null){ 
			ForestCtr fCtr = new ForestCtr();
			forests = fCtr.getUnOwned();
		}else{
			forests = o.getForests();
		}
		
		DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
		for(Forest f : forests){
			model.addElement(f.getName());
		}
		
		cmbForest.setModel(model);
		
		if(selected != null){
			cmbForest.setSelectedItem(selected);
		}
	}
	
	private boolean checkInput(){
		boolean ret = true;
		ForestCtr fCtr = new ForestCtr();
		
		if(fCtr.findForest((String)cmbForest.getSelectedItem()) == null){
			error(lblError2, "You must select a Forest!");
			ret = false;
		}
		
		if(txtSort.getText().length() <= 0){
			error(lblError4, "Sort cant be empty!");
			ret = false;
		}
		
		if(txtLifeSpan.getText().length() <= 0){
			error(lblError5, "LifeSpan cant be empty!");
			ret = false;
		}else{
			try{
				Double.parseDouble(txtLifeSpan.getText());
			}catch(NumberFormatException e){
				error(lblError5, "Lifespan must be a number!");
				ret = false;
			}
		}
		
		if(txtSquare.getText().length() <= 0){
			error(lblError6, "KM2 cant be empty!");
			ret = false;
		}else{
			try{
				Double.parseDouble(txtSquare.getText());
			}catch(NumberFormatException e){
				error(lblError6, "KM2 must be a number!");
				ret = false;
			}
		}
		
		if(txtCost.getText().length() <= 0){
			error(lblError7, "Cost cant be empty!");
			ret = false;
		}else{
			try{
				Double.parseDouble(txtCost.getText());
			}catch(NumberFormatException e){
				error(lblError7, "Cost must be a number!");
				ret = false;
			}
		}
		
		if(txtRevenue.getText().length() <= 0){
			error(lblError8, "Revenue cant be empty!");
			ret = false;
		}else{
			try{
				Double.parseDouble(txtRevenue.getText());
			}catch(NumberFormatException e){
				error(lblError8, "Revenue must be a number!");
				ret = false;
			}
		}
		
		return ret;
	}
	
	private void createTree(){
		if(checkInput()){
			ForestCtr fCtr = new ForestCtr();
			String forestName = (String)cmbForest.getSelectedItem();
			String sort = txtSort.getText();
			double lifespan = Double.parseDouble(txtLifeSpan.getText());
			double squareKilometer = Double.parseDouble(txtSquare.getText());
			double costPerSquareKilometer = Double.parseDouble(txtCost.getText());
			double revenuePerSquareKilometer = Double.parseDouble(txtRevenue.getText());
			fCtr.addTreeToForest(forestName, sort, lifespan, squareKilometer, costPerSquareKilometer, revenuePerSquareKilometer);
			created(lblCreated, sort + " added to " + forestName);
			clear();
		}
	}
	
	protected void updateTree() {
		if(checkInput()){
			ForestCtr fCtr = new ForestCtr();
			Forest newForest = fCtr.findForest((String)cmbForest.getSelectedItem());
			Forest oldForest = t.getForest();
			String sort = txtSort.getText();
			double lifespan = Double.parseDouble(txtLifeSpan.getText());
			double squareKilometer = Double.parseDouble(txtSquare.getText());
			double costPerSquareKilometer = Double.parseDouble(txtCost.getText());
			double revenuePerSquareKilometer = Double.parseDouble(txtRevenue.getText());
			
			t.setSort(sort);
			t.setLifespan(lifespan);
			t.setSquareKilometer(squareKilometer);
			t.setCostPerSquareKilometer(costPerSquareKilometer);
			t.setRevenuePerSquareKilometer(revenuePerSquareKilometer);
			
			if(newForest != oldForest){
				fCtr.moveTreeToForest(t, oldForest, newForest);
			}
			
			updater.closeMe(this);
		}
	}
	
}
